#pragma once
#include <iostream>
#include <pthread.h>
#include <semaphore.h>
#include <vector>

const int gmaxcap = 5;

template <class T>
class RingQueue
{
private:
    void P(sem_t &sem)
    {
        int n = sem_wait(&sem);
        if (n != 0)
        {
            std::cerr << "wait sem failed!!!" << std::endl;
        }
    }

    void V(sem_t &sem)
    {
        int n = sem_post(&sem);
        if (n != 0)
        {
            std::cerr << "post sem failed!!!" << std::endl;
        }
    }

public:
    RingQueue(int cap = gmaxcap) : _rq(cap), _cap(cap)
    {
        //一开始空间资源数量是5，由于生产者没有生产，故数据资源为0
        int n = sem_init(&_space, 0, gmaxcap);
        if (n != 0)
        {
            std::cerr << "_space init failed!!!" << std::endl;
            return;
        }
        n = sem_init(&_data, 0, 0);
        if (n != 0)
        {
            std::cerr << "_data init failed!!!" << std::endl;
            return;
        }

        _pstep = _cstep = 0;
    }

    void push(const T &in)
    {
        P(_space);//让空间资源-1
        _rq[_pstep++] = in;
        _pstep %= gmaxcap;
        V(_data);//生产完数据让数据资源+1

    }

    void pop(T *out)
    {
        P(_data);
        *out = _rq[_cstep++];
        _cstep %= gmaxcap;
        V(_space);
    }

    ~RingQueue()
    {
        int n = sem_destroy(&_space);
        if (n != 0)
        {
            std::cerr << "_space destroy failed!!!" << std::endl;
            return;            
        }
        n = sem_destroy(&_data);
        if (n != 0)
        {
            std::cerr << "_data destroy failed!!!" << std::endl;
            return;            
        }        
    }
private:
    std::vector<T> _rq;
    int _cap;
    sem_t _space;//生产者对应的空间资源
    sem_t _data; //消费者对应的数据资源
    int _pstep;//生产者开始下标
    int _cstep;//消费者开始下标
};